package com.example.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.example.Pojo.Result;
import com.example.utils.JwtUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

//这里关联了HandlerInterceptor这个实现类接口,下面要重写他的全部的方法
@Component //现在将其交给IOC容器看管理
//这里拦截器配置好之后,需要单独创建一个配置拦截器的类 创建一个包config单独存放这个类
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {
    @Override//目标资源(controller层)方法运行前运行,返回true: 放行,返回    false, 不放行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1, 获取请求url
        //这里通过request来调用.getRequestURL()获取请求的url地址,然后再将其转化为字符串类型,返回一个url地址
        String url = request.getRequestURL().toString();
        //查看请求的url
        log.info("请求的url:" + url);

        //2, 判断请求url中是否包含login.如果包含, 说明是登录操作,放行
        //这里通过contains()来判断url是否包含login
        if (url.contains("login")) {
            //如果存在将执行放行操作
            log.info("登录操作,放行");

            return true;
        }
        //3, 获取请求头中的令牌(token)
        //所有请求信息都在request
        //所以这里利用request来调用.getHeader("请求头的名字")将请求头的名字放入参数里得到jwt令牌
        String jwt = request.getHeader("token");

        //4, 判断令牌是否存在,如果不存在,返回错误结果(未登录)
        //这里需要用到StringUtils工具包  注意: 要用org.springframework.util.StringUtils这个包
        //现在通过StringUtils来调用.hasLength(jwt)将令牌jwt传递进去
        //判断该令牌是否有长度,如果是空,则返回jwt错误(未登录),如果有 放行
        if (!StringUtils.hasLength(jwt)) {
            log.info("请求的的token为空, 返回未登录的信息");
            //这里创建一个返回的请求参数
            Result error = Result.error("NOT_LOGIN");
            //现在将获得的error这个对象转化为JSON格式,这里需要利用到阿里巴巴提供的fastJSON工具包,需要在pom里创建依赖
            //下载好依赖后来创建JSONObject  注意:导包 com.alibaba.fastjson.JSONObject;这个包
            //现在通过JSONObject来调用.toJSONString()然后将返回的请求参数对象传递进去,返回一个JSON格式的字符串
            String NotLogin = JSONObject.toJSONString(error);
            //现在将获得到的JSON格式的字符串响应到浏览器中
            //现在通过墙砖后的response来调用 .getWriter() 创建一个输出流,然后在继续调用.write(NotLogin)将信息传递进来,最后响应到浏览器中
            response.getWriter().write(NotLogin);
            //结束当前判断
            return false;
        }

        //5, 解析token, 如果解析失败, 返回错误结果(未登录)
        //现在利用JwtUtils来调用.parseJWT()然后将得到的jwt令牌传递进去,然后进行判断
        //如果解析令牌成功则放行,如果失败的话将会出现异常报错,所以这里要进行一次try..catch来捕获异常
        try {
            JwtUtils.parseJWT(jwt);
        } catch (Exception e) {//如果解析失败
            e.printStackTrace();
            log.info("令牌解析失败,返回错误信息");
            Result error = Result.error("NOT_LOGIN");
            String NotLogin = JSONObject.toJSONString(error);
            response.getWriter().write(NotLogin);
            return false;
        }

        //6, 放行
        log.info("令牌合法,放行");
        return true;
    }

    @Override//目标资源(controller层)方法运行后运行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle运行了.......");
    }

    @Override//视图渲染完毕后运行,最后运行
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion运行了");
    }
}

